package com.bort.system.controller;

import com.bort.system.BortApplication;
import com.bort.system.common.DataContainer;
import com.bort.system.info.DeskInfo;
import com.bort.system.model.Cart;
import com.bort.system.model.Category;
import com.bort.system.model.Goods;
import com.bort.system.serial.SerialManager;
import com.bort.system.service.ClientService;
import com.bort.system.service.impl.ClientServiceImpl;
import com.bort.system.utils.ImageCache;
import com.bort.system.utils.Result;
import com.bort.system.view.CategoryItemView;
import com.bort.system.view.GoodsItemView;
import com.bort.system.view.LoginView;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;

public class MainAppController implements Initializable {

    private static int INDEX = 0;
    private static int MAX_INDEX = 10;

    private Timer timer;

    Stage dialogStage;

    @FXML
    FlowPane rootPane;

    @FXML
    FlowPane statePane;

    @FXML
    ListView<CategoryItemView> category;

    @FXML
    ListView<GoodsItemView> goods;

    @FXML
    ImageView goodsImage;

    @FXML
    Label goodsName;

    @FXML
    Label goodsPrice;

    @FXML
    Label goodsStock;

    @FXML
    Label goodsSold;

    @FXML
    Button minusBtn;

    @FXML
    Button plusBtn;

    @FXML
    TextField number;

    @FXML
    VBox orderBox;

    @FXML
    Label orderNoShow;

    @FXML
    Label orderTimeShow;

    @FXML
    Label countShow;

    @FXML
    Label totalShow;

    @FXML
    VBox deskOrderBox;

    @FXML
    ComboBox<Integer> deskNumber;

    @FXML
    ComboBox<String> playerNo;

    @FXML
    Label deskOrderNo;

    @FXML
    Label deskOrderTime;

    @FXML
    Label deskCount;

    @FXML
    Label deskTotal;

    @FXML
    Button orderConfirm;

    @FXML
    Button deskOrderConfirm;

    @FXML
    Button onAccountBtn;

    @FXML
    Button orderBtn;

    Label connected;

    SerialManager serialManager;

    ClientService clientService;

    private Category indexCate;

    private Goods indexGoods;

    @FXML
    void onExitClick(){
        Stage mainApp = BortApplication.getStage();
        mainApp.close();
        BortApplication.showView(LoginView.class);
    }

    @FXML
    void toBrowser(){
        HostServices services = BortApplication.getAppHostServices();
        services.showDocument("http://39.99.39.55:9880");
    }

    @FXML
    void onHelpClick(){
        Stage stage = BortApplication.getStage();
        DialogPane dialogPane = new DialogPane();
        dialogPane.setContentText("开发着联系电话: 18902123716");
        dialogPane.setPrefWidth(320);
        dialogPane.setPrefHeight(90);
        if(dialogStage == null){
            dialogStage = new Stage();
        }
        dialogStage.setY(stage.getY() + 60);
        dialogStage.setX(stage.getX() + 120);
        Scene scene = new Scene(dialogPane);
        dialogStage.setScene(scene);
        dialogStage.show();
        dialogStage.setIconified(false);
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        clientService = ClientServiceImpl.getInstance();
        BortApplication.getStage().setResizable(true);
        rootPane.setStyle("-fx-background-color: white");
        if(DataContainer.deskContainer == null){
            DataContainer.deskContainer = new HashMap<>();
        }
        if(DataContainer.deskCtrlMap == null){
            DataContainer.deskCtrlMap = new HashMap<>();
        }
        List<DeskInfo> list = clientService.getAllDesk();
        for (DeskInfo tDesk : list) {
            initData(tDesk);
        }
        initDeviceState();
        DataContainer.mainAppController = this;
        initShop();
    }

    private void initShop() {
        initCategory();
        initGoods(true);
        initBusiness();
    }

    private void initBusiness() {
        if(indexGoods == null){
            number.setText(null);
            goodsImage.setImage(ImageCache.getImage("/img/default_goods.png"));
            goodsName.setText("商品名称");
            goodsPrice.setText("0.00￥");
            goodsStock.setText("库存:0");
            goodsSold.setText("已售:0");
            minusBtn.setDisable(true);
            plusBtn.setDisable(true);
            number.setDisable(true);
        }else{
            number.setText("1");
            goodsImage.setImage(ImageCache.getImage(DataContainer.loadImageUrl+indexGoods.getGoodsImage()));
            goodsName.setText(indexGoods.getGoodsName());
            goodsPrice.setText(indexGoods.getPrice().toString()+"￥");
            goodsStock.setText("库存:"+indexGoods.getStock());
            goodsSold.setText("已售:"+indexGoods.getSold());
            minusBtn.setDisable(false);
            plusBtn.setDisable(false);
            number.setDisable(false);
            number.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
                @Override
                public void handle(KeyEvent event) {
                    if(StringUtils.isNumeric(number.getText())){
                        int num = Integer.parseInt(number.getText());
                        if(num > indexGoods.getStock()){
                            number.setText(indexGoods.getStock().toString());
                        }else if(num <= 0){
                            number.setText("1");
                        }
                    }else{
                        number.setText(null);
                    }
                }
            });
            orderBtn.setDisable(false);
            if (indexGoods.getStock() == 0) {
                orderBtn.setDisable(true);
            }
            initDeskNoCombo();
            createOrder(2,null,null,null,0,null);
            createDeskOrder(1,null,null,null,0,null);
        }
    }

    private void initDeskNoCombo() {
        Iterator<Integer> dataItr = DataContainer.deskContainer.keySet().iterator();
        Integer two = 2;
        boolean btnActive = false;
        List<Integer> deskNoList = new ArrayList<>();
        while (dataItr.hasNext()){
            Integer deskId = dataItr.next();
            DeskInfo deskInfo = DataContainer.deskContainer.get(deskId);
            if("2".equals(deskInfo.getStatus()) && two.equals(deskInfo.getTimeLimit()) ){
                btnActive = true;
                deskNoList.add(deskInfo.getDeskNo());
            }
        }
        if(btnActive){
            onAccountBtn.setDisable(false);
        }else{
            onAccountBtn.setDisable(true);
        }
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                ObservableList deskNoItems = FXCollections.observableList(deskNoList);
                deskNumber.setItems(deskNoItems);
                deskNumber.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Integer>() {
                    @Override
                    public void changed(ObservableValue<? extends Integer> observable, Integer oldValue, Integer newValue) {
                        Integer value  = newValue!=null?newValue:oldValue;
                        if(StringUtils.isNotEmpty(deskOrderNo.getText())){
                            deskOrderConfirm.setDisable(false);
                        }
                        Iterator<Integer> deskItr = DataContainer.deskContainer.keySet().iterator();
                        while (deskItr.hasNext()){
                            Integer deskId = deskItr.next();
                            DeskInfo desk = DataContainer.deskContainer.get(deskId);
                            if(value.equals(desk.getDeskNo())){
                                playerNo.setValue(null);
                                String playerStr = desk.getPlayer();
                                if(StringUtils.isNotEmpty(playerStr)){
                                    System.out.println(playerStr);
                                    String[] players = playerStr.split(",");
                                    ObservableList<String> items = FXCollections.observableList(Arrays.asList(players));
                                    playerNo.setItems(items);
                                }else{
                                    playerNo.setItems(null);
                                }
                            }
                        }
                    }
                });
            }
        });
    }


    private void initGoods(boolean lazyLoad) {
        if(indexCate != null){
            List<Goods> goodsInfos = clientService.loadGoodsByCategoryId(indexCate.getId());
            List<GoodsItemView> viewList = new ArrayList<>();
            for (Goods goodsInfo : goodsInfos) {
                GoodsItemView gView = new GoodsItemView(goodsInfo,lazyLoad);
                viewList.add(gView);
            }
            ObservableList<GoodsItemView> goodsOptions = FXCollections.observableList(viewList);
            goods.setItems(goodsOptions);
            for (GoodsItemView goodsView : viewList) {
                goodsView.setOnMouseClicked(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent event) {
                        indexGoods = goodsView.getData();
                        initBusiness();
                    }
                });
            }
        }

    }

    private void initCategory() {
        Result<List<Category>> result = clientService.loadAllCategories(new HashMap<>());
        if(result.getCode() == 200){
            List<Category> list = result.getData();
            List<CategoryItemView> items = new ArrayList<>();
            for (Category cate : list) {
                CategoryItemView item = new CategoryItemView(cate);
                items.add(item);
            }
            ObservableList<CategoryItemView> cateOptions = FXCollections.observableList(items);
            category.setItems(cateOptions);
            if(list.size() > 0){
                indexCate = list.get(0);
            }

            for (CategoryItemView item : items) {
                item.setOnMouseClicked(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent event) {
                        indexCate = item.getData();
                        initGoods(false);
                    }
                });
            }
        }
    }


    @FXML
    void onAddNumber(MouseEvent event){
        int num = null !=number.getText()? Integer.parseInt(number.getText()):0;
        if(num < indexGoods.getStock()){
            number.setText(Integer.toString(num + 1));
        }
    }

    @FXML
    void onSubtractNumber(MouseEvent event){
        int num = null !=number.getText()? Integer.parseInt(number.getText()):0;
        if(num > 1){
            number.setText(Integer.toString(num - 1));
        }
    }

    @FXML
    void onOrderCreate(MouseEvent event){
        createOrder(1);
    }


    @FXML
    void onChargeAccount(MouseEvent event){
        createOrder(2);
    }

    void createOrder(int sourceBtn){
        Date now = new Date();
        String orderNum = "ON"+ DateFormatUtils.format(now, "yyMMddHHmmss");
        String time = DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss");
        int num = null !=number.getText()? Integer.parseInt(number.getText()):0;
        BigDecimal total = indexGoods.getPrice().multiply(new BigDecimal(num));
        playerNo.setItems(null);
        if(sourceBtn == 1){
            createOrder(sourceBtn,now,orderNum,time,num,total);
            createDeskOrder(1,null,null,null,0,null);
        }else{
            createOrder(2,null,null,null,0,null);
            createDeskOrder(2,now,orderNum,time,num,total);
            initDeskNoCombo();
        }
    }

    private void createDeskOrder(int type, Date now, String orderNum, String time, int num, BigDecimal total) {
        if(type == 2){
            deskOrderBox.setStyle("-fx-background-color: white;-fx-padding: 10 10 10 10;-fx-border-color: grey;-fx-border-width: 0 1 0 0");
            deskOrderNo.setText(orderNum);
            deskOrderTime.setText(time);
            deskCount.setText(indexGoods.getPrice()+"x"+num);
            deskTotal.setText(total.toString()+"￥");
        }else{
            deskOrderBox.setStyle("-fx-background-color: transparent;-fx-padding: 10 10 10 10;-fx-border-color: grey;-fx-border-width: 0 1 0 0");
            deskNumber.setValue(null);
            deskNumber.setItems(null);
            playerNo.setValue(null);
            playerNo.setItems(null);
            deskOrderNo.setText(null);
            deskOrderTime.setText(null);
            deskCount.setText(null);
            deskTotal.setText(null);
            deskOrderConfirm.setDisable(true);
        }
    }

    void createOrder(int type,Date now,String orderNum,String time,int num,BigDecimal total){
        if(type == 1){
            orderBox.setStyle("-fx-background-color: white;-fx-padding: 10 10 10 10;-fx-border-color: grey;-fx-border-width: 0 1 0 0");
            orderNoShow.setText(orderNum);
            orderTimeShow.setText(time);
            countShow.setText(indexGoods.getPrice()+"x"+num);
            totalShow.setText(total.toString()+"￥");
            orderConfirm.setDisable(false);
        } else {
            orderBox.setStyle("-fx-background-color: transparent;-fx-padding: 10 10 10 10;-fx-border-color: grey;-fx-border-width: 0 1 0 0");
            orderNoShow.setText(null);
            orderTimeShow.setText(null);
            countShow.setText(null);
            totalShow.setText(null);
            orderConfirm.setDisable(true);
        }
    }

    @FXML
    void onOrderConfirmClick(MouseEvent mouseEvent){
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                createDialog(BortApplication.getStage());
            }
        });
    }

    public void createDialog(Window owner) {
        Dialog<String> dialog = new Dialog();
        dialog.setTitle("睿美台球管理系统");
        dialog.setWidth(400);
        dialog.setHeight(300);
        dialog.initOwner(owner);

        DialogPane dialogPane = new DialogPane();

        AnchorPane anchor = new AnchorPane();
        anchor.minHeight(300);
        anchor.minWidth(400);
        Label msg = new Label("请确认客户已支付并点击确定");
        msg.setPrefWidth(300);
        msg.setStyle("-fx-font-size: 18");
        msg.setLayoutX(25);
        msg.setLayoutY(15);
        anchor.getChildren().add(msg);
        dialogPane.setContent(anchor);

        // 设置按钮
        dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
        Button okBtn = (Button) dialogPane.lookupButton(ButtonType.OK);

        okBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                String text = number.getText();
                if(StringUtils.isNumeric(text)){
                    int num = Integer.parseInt(text);
                    String orderNo = orderNoShow.getText();
                    Result result = clientService.sale(indexGoods,orderNo,num);
                    if(result.getCode() == 200){
                        indexGoods.setStock(indexGoods.getStock() - num);
                        indexGoods.setSold(indexGoods.getSold() + num);
                        initBusiness();
                    }
                }
                dialog.close();
            }
        });

        dialog.setDialogPane(dialogPane);
        dialog.show();

    }

    @FXML
    void onPutCartClick(MouseEvent event){
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                String text = number.getText();
                if(StringUtils.isNumeric(text)) {
                    int num = Integer.parseInt(text);
                    String orderNo = deskOrderNo.getText();
                    DeskInfo deskInfo = null;
                    Integer deskNo = deskNumber.getValue();
                    Iterator<Integer> deskItr = DataContainer.deskContainer.keySet().iterator();
                    while (deskItr.hasNext()) {
                        Integer itemId = deskItr.next();
                        DeskInfo desk = DataContainer.deskContainer.get(itemId);
                        if (deskNo.equals(desk.getDeskNo())) {
                            deskInfo = desk;
                        }
                    }
                    String playerName = playerNo.getValue();
                    Result<List<Cart>> result = clientService.putInCart(indexGoods, orderNo, num, deskInfo.getId(), playerName);
                    if(result.getCode() == 200){
                        indexGoods.setStock(indexGoods.getStock() - num);
                        indexGoods.setSold(indexGoods.getSold() + num);
                        initBusiness();
                        DeskController deskCtrl = DataContainer.deskCtrlMap.get(deskInfo.getId());
                        deskCtrl.refreshDeskData();
                        deskCtrl.flickerCart();
                    }
                }
            }
        });
    }



    public void setConnectState(){
        if(serialManager.openingPort == null){
            connected.setText("请点击连接灯光控制设备");
            connected.setTextFill(Color.LIGHTSEAGREEN);
        }else{
            connected.setText("已连接灯光控制设备");
            connected.setTextFill(Color.MEDIUMSLATEBLUE);
        }
    }

    private void initDeviceState() {
        serialManager = SerialManager.getInstance();
        connected = new Label();
        setConnectState();
        connected.setPrefHeight(40);
        connected.setPrefWidth(220);
        connected.setPadding(new Insets(0,0,0,10));
        statePane.getChildren().add(connected);

        connected.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if(serialManager.openingPort == null && INDEX == 0){
                    serialManager.reconnect();
                    connected.setText("正在搜索灯光控制设备");
                    timer = new Timer();
                    timer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            Platform.runLater(new Runnable() {
                                @Override
                                public void run() {
                                    connected.setText(connected.getText().concat(">"));
                                }
                            });
                            INDEX++;
                            if(INDEX >= MAX_INDEX){
                                INDEX = 0;
                                Platform.runLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        setConnectState();
                                    }
                                });
                                timer.cancel();
                            }
                        }
                    },200,200);
                }
            }
        });

    }

    void initData(DeskInfo tDesk){
        try{
            DataContainer.deskIndex = tDesk.getId();
            DataContainer.deskContainer.put(tDesk.getId(),tDesk);
            FXMLLoader fxmlLoader = new FXMLLoader(MainAppController.class.getResource("/view/deskView.fxml"));
            AnchorPane root = (AnchorPane)fxmlLoader.load();
            rootPane.getChildren().add(root);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

}
